/********************************************************************************
    @文件名：         ringbuffer.c
    @作者：           矛盾聚合体
    @版本：           Version 1.0
    @日期：           2020-2-2
    @描述：
    @历史：
********************************************************************************/
#include "ringbuffer.h"

void RingBuffer::init(void)
{
    head = 0;
    tail = 0;
}

void RingBuffer::clear(void)
{
    head = 0;
    tail = 0;
}

char RingBuffer::enqueueChar(char ch)
{
    if(canEnqueue(1) == false)return RING_BUF_OVERFLOW;  // 缓冲区溢出
    // 串口收到一个字符
    // 将从串口接收到的字符填充到缓冲区中
    ringBuf[tail] = ch;
    // 缓冲区尾部移动
    tail++;
    if(tail == RING_BUF_SIZE)tail = 0;  // 如果缓冲区尾部到达缓冲区末端，则重设为首端
    return RING_BUF_ENQUEUE_SUCCEEDED; // 缓冲区入栈成功
}

char RingBuffer::enqueueArr(char * Arr, int size)
{
    char * pArr = Arr;
    // 溢出判断
	if (canEnqueue(size) == false)return RING_BUF_OVERFLOW;  // 缓冲区溢出
    // 数据分段
    int part0Size = (tail + size - 1 < RING_BUF_SIZE) ? size : RING_BUF_SIZE - tail;
    int part1Size = (tail + size - 1 < RING_BUF_SIZE) ? 0 : size - part0Size;
    // 数据拷贝
    memcpy(ringBuf + tail, pArr, part0Size);
    if(part1Size != 0)memcpy(ringBuf, pArr + part0Size, part1Size);
    // 数据尾移动
    tail = (tail + size) % RING_BUF_SIZE;
    return RING_BUF_ENQUEUE_SUCCEEDED;
}

char RingBuffer::dequeueChar(char * ch)
{
    if((tail + RING_BUF_SIZE - head) % RING_BUF_SIZE <= 0)return RING_BUF_EMPTY;  // 缓冲区为空
    // 提取到一个字符
    // 将提取到的字符填充到临时变量中
    *ch = ringBuf[head];
    // 缓冲区头部移动
    head++;
    if(head == RING_BUF_SIZE)head = 0;  // 如果缓冲区头部到达缓冲区末端，则重设为首端
    return RING_BUF_DEQUENE_SUCCEEDED; // 缓冲区出栈成功
}

char RingBuffer::dequeueArr(char * Arr, int size)
{
    char * pArr = Arr;
    // 溢出判断
    if(available() < size)return RING_BUF_EMPTY;
    // 数据分段
    int part0Size = (head + size - 1 < RING_BUF_SIZE) ? size : RING_BUF_SIZE - head;
    int part1Size = (head + size - 1 < RING_BUF_SIZE) ? 0 : size - part0Size;
    // 数据拷贝
    memcpy(pArr, ringBuf + head, part0Size);
    if(part1Size != 0)memcpy(pArr + part0Size, ringBuf, part1Size);
    Arr[size] = '\0';
    // 数据尾移动
    head = (head + size) % RING_BUF_SIZE;
    return RING_BUF_DEQUENE_SUCCEEDED;
}

char RingBuffer::getLine(char * line)
{
    if(hasCRLFRingBuffer() == 0)return RING_BUF_EMPTY;
    dequeueArr(line, hasCRLFRingBuffer());
    return RING_BUF_DEQUENE_SUCCEEDED;
}

char RingBuffer::peekChar(char * ch)
{
    if(isEmpty() == true)return RING_BUF_EMPTY;
    *ch = ringBuf[head];
    return RING_BUF_PEEK_SUCCEEDED;
}

char RingBuffer::isEmpty(void)
{
    if((tail + RING_BUF_SIZE - head) % RING_BUF_SIZE == 0)return true;  // 缓冲区为空
    else return false;
}

char RingBuffer::isOverflow(void)
{
    if((tail + RING_BUF_SIZE - head) % RING_BUF_SIZE >= RING_BUF_SIZE - 1)return true;  // 缓冲区溢出
    else return false;
}

int RingBuffer::available(void)
{
    return (tail + RING_BUF_SIZE - head) % RING_BUF_SIZE;
}

int RingBuffer::availableLine(void)
{
    if(hasCRLFRingBuffer() > 0)return 1;
    else return 0;
}

int RingBuffer::freeSpace(void)
{
    return (RING_BUF_SIZE - (tail + RING_BUF_SIZE - head) % RING_BUF_SIZE);
}

int RingBuffer::size(void)
{
    return RING_BUF_SIZE;
}

int RingBuffer::hasCRLFRingBuffer(void)
{
    int _head = head;
    int charNum = available();
    int counter = 0;
    while(counter < charNum)
    {
        counter++;
        if(ringBuf[_head] == '\n')return counter;
		_head++;
        if(_head == RING_BUF_SIZE)_head = 0;
    }
    return 0;
}
bool RingBuffer::canEnqueue(int charNum)
{
	return (available() + charNum < RING_BUF_SIZE) ? true : false;
}
